<!DOCTYPE html>



  


<html class="theme-next gemini use-motion" lang="zh-Hans">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta name="theme-color" content="#222">



  
  
    
    
  <script src="/lib/pace/pace.min.js?v=1.0.2"></script>
  <link href="/lib/pace/pace-theme-minimal.min.css?v=1.0.2" rel="stylesheet">







<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />







<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />

<link href="/css/main.css?v=5.1.4" rel="stylesheet" type="text/css" />


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png?v=5.1.4">


  <link rel="mask-icon" href="/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="freeswitch," />





  <link rel="alternate" href="/atom.xml" title="搁浅丶岁月的变迁" type="application/atom+xml" />






<meta name="description" content="1.调试与排错根据问题现象, 系统提供的日志, 线索等查找原因  1）解决问题的一般方法和流程      发现问题, 定位问题, 分析问题, 解决问题      Alice告诉我们, 她通过Freeswitch呼叫Bob, 能打通,但没有声音          首先, 两端都听不到, 还是一方没有声音          其次, 每次都听不到,还是偶尔听不到, 偶尔是在什么情况下听不到">
<meta name="keywords" content="freeswitch">
<meta property="og:type" content="article">
<meta property="og:title" content="10.基本技能">
<meta property="og:url" content="http://yoursite.com/2017/12/23/2017-12-23-10.基本技能/index.html">
<meta property="og:site_name" content="搁浅丶岁月的变迁">
<meta property="og:description" content="1.调试与排错根据问题现象, 系统提供的日志, 线索等查找原因  1）解决问题的一般方法和流程      发现问题, 定位问题, 分析问题, 解决问题      Alice告诉我们, 她通过Freeswitch呼叫Bob, 能打通,但没有声音          首先, 两端都听不到, 还是一方没有声音          其次, 每次都听不到,还是偶尔听不到, 偶尔是在什么情况下听不到">
<meta property="og:locale" content="zh-Hans">
<meta property="og:updated_time" content="2018-05-28T08:47:46.372Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="10.基本技能">
<meta name="twitter:description" content="1.调试与排错根据问题现象, 系统提供的日志, 线索等查找原因  1）解决问题的一般方法和流程      发现问题, 定位问题, 分析问题, 解决问题      Alice告诉我们, 她通过Freeswitch呼叫Bob, 能打通,但没有声音          首先, 两端都听不到, 还是一方没有声音          其次, 每次都听不到,还是偶尔听不到, 偶尔是在什么情况下听不到">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Gemini',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="http://yoursite.com/2017/12/23/2017-12-23-10.基本技能/"/>





  <title>10.基本技能 | 搁浅丶岁月的变迁</title>
  








</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>
    <a href="https://github.com/liaoren512"><img style="position: absolute; top: 0; left: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_left_red_aa0000.png" alt="Fork me on GitHub"></a>
    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/"  class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">搁浅丶岁月的变迁</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle">没有虽败犹荣，只有成王败寇。</p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br />
            
            标签
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br />
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
            
            归档
          </a>
        </li>
      

      
        <li class="menu-item menu-item-search">
          
            <a href="javascript:;" class="popup-trigger">
          
            
              <i class="menu-item-icon fa fa-search fa-fw"></i> <br />
            
            搜索
          </a>
        </li>
      
    </ul>
  

  
    <div class="site-search">
      
  <div class="popup search-popup local-search-popup">
  <div class="local-search-header clearfix">
    <span class="search-icon">
      <i class="fa fa-search"></i>
    </span>
    <span class="popup-btn-close">
      <i class="fa fa-times-circle"></i>
    </span>
    <div class="local-search-input-wrapper">
      <input autocomplete="off"
             placeholder="搜索..." spellcheck="false"
             type="text" id="local-search-input">
    </div>
  </div>
  <div id="local-search-result"></div>
</div>



    </div>
  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2017/12/23/2017-12-23-10.基本技能/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="廖壬">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/ichgo.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="搁浅丶岁月的变迁">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">10.基本技能</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2017-12-23T00:00:00+08:00">
                2017-12-23
              </time>
            

            

            
          </span>

          

          
            
          

          
          

          
            <span class="post-meta-divider">|</span>
            <span class="page-pv"><i class="fa fa-file-o"></i>
            <span class="busuanzi-value" id="busuanzi_value_page_pv" ></span>
            </span>
          

          
            <div class="post-wordcount">
              
                
                <span class="post-meta-item-icon">
                  <i class="fa fa-file-word-o"></i>
                </span>
                
                  <span class="post-meta-item-text">字数统计&#58;</span>
                
                <span title="字数统计">
                  
                </span>
              

              
                <span class="post-meta-divider">|</span>
              

              
                <span class="post-meta-item-icon">
                  <i class="fa fa-clock-o"></i>
                </span>
                
                  <span class="post-meta-item-text">阅读时长 &asymp;</span>
                
                <span title="阅读时长">
                  
                </span>
              
            </div>
          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <h2 id="1-调试与排错"><a href="#1-调试与排错" class="headerlink" title="1.调试与排错"></a>1.调试与排错</h2><pre><code>根据问题现象, 系统提供的日志, 线索等查找原因

1）解决问题的一般方法和流程

    发现问题, 定位问题, 分析问题, 解决问题

    Alice告诉我们, 她通过Freeswitch呼叫Bob, 能打通,但没有声音

        首先, 两端都听不到, 还是一方没有声音

        其次, 每次都听不到,还是偶尔听不到, 偶尔是在什么情况下听不到

        再次, Alice和Bob使用的是什么UA,什么型号

        网络情况怎么样,用ADSL,宽带,还是手机上网

    Alice普通用户, 她可能不知道这些, 这种情况下,我们需要多问一下Alice, 确认实际上是否与Alice描述的一致, 能否重新等

        核实问题的现象, 假定Alice不可信,她可能描述不清楚, 最好自己试

        问题能否重现



        分段法

            一个问题可能涉及多个环节,我们把这些环节从逻辑和功能上分开,一段段检查

        换位思考法

            Alice打给Bob没有声音, 那么Bob打开Alice有没有声音,能不能让Alice或Bob换其他话机试试

    显示当前通话Channel的UUID

        show channels

    调试媒体相关的信息

        uuid_debug_media uuid both on/off

    使用回拨命令录音

        originate user/1002 &amp;record(/tmp/test.wav)

2）查看日志

    打开BEBUG级别的日志

        console loglevel debug
</code></pre><h2 id="2-使用外部工具抓包"><a href="#2-使用外部工具抓包" class="headerlink" title="2.使用外部工具抓包"></a>2.使用外部工具抓包</h2><pre><code>对IP包进行全面分析,或存档,需要使用外部的工具抓包

1）tcpdump

    抓取5060端口上的SIP包

        tcpdump -nq -s 0 -A -vvv -i etho0 port 5060

        -n,q 表示不进行域名翻译及减少输出内容

        -s 0 表示不限制包长,争取抓最大的长度

        -A 表示以ASCII方式输出

        -v 表示详细程度,v越多越详细

        -i 表示指定的网卡

        port 5060 表示过滤器

    写入文件 -w

        tcpdump -nq -s 0 -i eho0 -w /tmp/dump.pcap udp

    针对用户抓包

        tcpdump -i etho0 -s 0 -A host 192.168.7.5 and port 65272

2）tshark

    直接在命令行运行tshark

    从第一块网卡上抓包

        tshark -i eth0

    抓包结果写入pcap文件

        tshark -i eth0 -w /tmp/dump.pcap

    与tcpdump相比,tshark能认识更多的协议,能直观看到收发的SIP包

        tshark host 192.168.1.9 and port 5060

3）ngrep

    提供类似于Freeswitch内部抓包输出的显示方式, 比较直观

        ngrep -p -q -W byline port 5060

        -p 表示不使用混杂模式

        -q 表示使用安静模式,仅输出包头和包的载荷

        -W 表示选择一种显示输出方式,byline 按换行符进行换行

        port 5060 是一个过滤器,只想看我们关心的包

    对内容过滤

        ngrep -p -q &apos;139xxxxxxxxx&apos; -W byline port 5060

4）pcapsipdump

    将不同通话IP包存到不同的文件,某一路通话所有的SIP和RTP数据都存到同一个文件

        pcapsipdump -i eth0 -d /tmp/sipdump/
</code></pre><p>…………….</p>
<h2 id="4-originate命令示例解析"><a href="#4-originate命令示例解析" class="headerlink" title="4.originate命令示例解析"></a>4.originate命令示例解析</h2><pre><code>originate命令用于从Freeswitch中向外发起一个呼叫

1）使用格式和参数

    call url

        呼叫字符串(Dial String)

        originate user/1000 &amp;echo

        user/1000,就是呼叫字符串,表示从本地的注册用户中查找该用户的联系地址

    同振: 同时呼叫1000和1001,哪个先接听则接通哪个,另一路自动挂断

        originate user/1000,user/1001 &amp;echo

    顺振:　第一个呼叫失败则呼叫第二个

         originate user/1000|user/1001 &amp;echo

2）转入Dialplan

    接听后进入public Dialplan查找路由

        originate user/1000 1001 XML public

3）更改主叫号码

    000000000,是Freeswitch发起呼叫时默认使用的主叫号码,我们可以指定主叫号码

        originate user/1000 &amp;echo XML default &apos;Seven Du&apos; 777

        如果参数有空格,需要用单引号引起来

4）处理呼叫超时

    不是对方不接电话超时的秒数, 而是对方在收到我们INVITE消息后, 不回复100 Trying消息的时间

    一般来说这种情况下IP地址不可达

        sofia profile internal siptrace on

        originate sofia/internal/1000/192.168.100.100

        由于地址不存在,发送INVITE消息后,没有收到100Trying,于是在1s后重发,如果还收不到则于2s,4s重发

        10s超时,超过10s后失败,返回NO_ANSWER

5）originate命令是阻塞的

    如果执行上述命令, 则无法出入其他命令或取消呼叫

    使用bgapi可以避免阻塞

        bgapi originate sofia user/1000 &amp;echo

    开启另一个fs_cli,使用show channels找到呼叫UUID,然后uuid_kill

6）使用通道变量

    通道变量可以影响呼叫行为, 在使用originate时也可以使用通道变量

    改变主号名称和号码

        originate {origination_caller_id_name=&apos;Seven Du&apos;,origination_caller_id_number=7777}user/1000 &amp;echo

    多个通道变量之间使用逗号隔开, 可以使用反斜杠进行转义

        originate {absolute_codec_string=G729\,PCMU} user/1000 &amp;echo

    局部通道变量,先呼叫某用户分机号, 超时则通过网关1呼叫手机号, 再超时通过网关2呼叫

        originate {var1=1}[leg_timeout=0]user/1000 | [leg_timeout=20]sofia/gateway/gw1/1300000000| [leg_timeout=20]sofia/gateway/gw2/130000000

        leg_timeout只应用于靠近它的一条腿, 用于定义超时, 等待对方返回媒体(183或200)的超时时间

7）Early Media对呼叫的影响

    如果我们呼叫本地的IP, 对方回180Ring, 同样的情况下如果通过网关对PSTN用户呼叫, 则PSTN往往返回Early Media, 也就是前期的振铃音或彩铃

    PSTN呼叫失败也返回Early Media,如&quot;您拨打的电话忙...&quot;



    Early Media对我们没有意义, 在主动外呼的应用中, 希望用户真正接听以后才对他放音

    有一个参数可以做到

        originate {ignore_early_media=true}sofia/gateway/gw/1380000000 &amp;playback(/tmp/test.wav)

        通过指定ingnore_early_media变量, Freeswitch在发起呼叫时忽略对方返回的Early Media,等收到正常应答(200)才返回

8）bridge也使用originate

    我们使用originate命令发起一个呼叫, 接通1000和1001两个号码

        originate user/1000 &amp;bridge(user/1001)

    当originate发起呼叫时, 建立一个Channel, 然后呼叫1000, 1000接听后, 在该Channel执行bridge, bridge会建立另一个Channel来呼叫1001

        1001接通后,bridge会把它们的媒体也桥接起来, 此时进入正常通话

9）bridge中的Early Media

    如果b-leg返回SIP的183, 则Freeswitch也会想a-leg返回183, 因此将b-leg收到的媒体发到a-leg上,a-leg就听到了回铃音(彩铃)

    如果b-leg返回180, 则由于a-leg已经接听, 因此Freeswitch认为无法为a-leg发送180 Ringing消息,因此a-leg,b-leg振铃期间听不到任何声音

10）bridge中的主叫号码

    设置主叫号码

        originate {origination_caller_id_number=7777} user/1000 &amp;echo

    我们使用bridge呼叫b-leg

        originate {origination_caller_id_number=7777} user/1000 &amp;bridge(user/1001)

        Freeswitch发现a-leg是一个回呼, 当a-leg接听后, 再作为主叫去呼叫b-leg, a-leg的主叫号码变成了1000, 桥接的时候变成了1001, 显示主叫号码是1000
</code></pre><h2 id="5-呼叫是怎么工作的"><a href="#5-呼叫是怎么工作的" class="headerlink" title="5.呼叫是怎么工作的?"></a>5.呼叫是怎么工作的?</h2><pre><code>假设从1000呼叫1001

    1000的SIP话机作为UAC会发送INVITE请求到Freeswitch 5060端口,到达internal的Profile配置的UAS

    UAS收到INVITE后返回100响应码, 表示我收到了你的请求,对INVITE鉴权,Freeswitch会到用户目录查找相应的用户

    找到1000.xml配置的用户信息,并根据配置的用户名,密码鉴权,通过后,收到用户信息

    进入路由阶段,查找Dialplan,

        &lt;user id=&quot;1000&quot;&gt;

            &lt;variables&gt;

                &lt;variable name=&quot;accountcod&quot; value=&quot;1000&quot;/&gt;

                &lt;variable name=&quot;user_context&quot; value=&quot;default&quot;/&gt;        --&gt;default

            .....



        &lt;include&gt;

            &lt;context name=&quot;default&quot;&gt;                                 --&gt;default

                &lt;extension name=&quot;record&quot;&gt;

                ....



    查找Dialplan, 会帮你找到1001这个用户, 并执行bridge user/1001,

        user/1001 被称为呼叫字符串

    再次查找Directory, 找到1001.xml参数

        1001是被叫, 它会找到1001实际注册的位置,用data-string参数表示

        该参数放到directory/default.xml

            &lt;param name=&quot;dial_string&quot; value=&quot;{sip_invite_domain=${dialed_domain},presence_id=${dialed_user}@${dialed_domain}}&amp;{sofia_contact{${dialed_user}@${dialed_domain})}&quot;/&gt;

        sofia_contact会查找数据库,找到1001实际注册的Contact地址,并返回真正的呼叫字符串

        返回1001注册的Contact

            sofia_contact 1001@192.168.1.109

    找到呼叫字符串后, Freeswitch又启动另一个会话,作为UAC给1001发送INVITE请求, 如果1001接通,则向Freeswitch回送200,

    Freeswitch向1000回200 OK, 通话开始

        打开跟踪命令

            sofia profile internal siptrace on

        关闭调试命令

            sofia profile internale siptrace off
</code></pre><h2 id="6-Freeswitch图形用户界面简介"><a href="#6-Freeswitch图形用户界面简介" class="headerlink" title="6.Freeswitch图形用户界面简介"></a>6.Freeswitch图形用户界面简介</h2><pre><code>对于Freeswitch新手或维护人员来讲,更喜欢使用图形界面操作Freeswitch

开发Freeswitch的GUI有两种方法:

    提供图形界面, 后台修改Freeswitch的XML配置文件,调用reloadxml

    使用Freeswitch提供的xml_curl接口, 提供一个HTTP服务器向Freeswitch提供XML, 可以管理多台Freeswitch, 并适合大规模部署

1）FusionPBX

    使用PGP开发的Freeswitch GUI, 支持Linux, Windows, BSD, Mac OS等多种操作系统, 支持POST供热SQL, MySQL, SQLite等

    它通过将数据库存储到数据库中, 并修改本地的XML配置文件

        支持无限的分机, IVR, 呼叫组, 传真, 会议, 队列, 呼叫前转, 点击拨号以及实时呼叫状态显示等诸多特性

2）blue.box

    使用PHP/MySQL技术开发, 基于Asterisk的GUI FreePBX, 号称FreePBX V3, 使用修改本地XML配置文件并重新加载的工作方式

        支持普通用户, 分机, 路由管理, 支持多语言, 多租户

3）Freeswitch Portal

    与其他GUI系统不同, 它作为GUI系统的补充, 提供一些开发者常用的功能

    Freeswitch Portal内置于Freeswitch, 依赖于mod_xml_rpc模块提供的Webserver

    该模块是默认编译的,但不加载,只需要加载该模块,即可使用

        load mod_xml_rpc

    如果想让该模块随着Freeswitch启动而自动加载, 可以在conf/autoload_configs/modules.xml中将模块的注释去掉

        &lt;load module=&quot;mod_xml_rpc&quot;/&gt;

    使用浏览器打开http://localhost:8080/portal,用户名,密码: freeswitch,works

        密码在/conf/autoload_configs/xml_rpc.conf.xml配置

    系统菜单

        Users: 显示所有用户

        Calls: 显示当前呼叫状态, 选中Auto Update,表示实时更新

        Channels: 显示所有Channel的状态, 它是实时更新的

        Show: 显示Freeswitch内部信息

            注册信息, 已加载模块, App, API等

    网页调试

        控制台输入 event(&quot;ALL&quot;),订阅全部事件

            这时候打电话, 就可以看到调试窗口输出各种事件的名字

            读者就知道打一个电话大体会产生那些事件

        不想看详细信息, 控制台输入

            global_debug_event = true

        直接执行Freeswitch的API命令

            api(&quot;status&quot;);

            api(&quot;sofia status&quot;);

            bgapi(&quot;originate user/1000 &amp;echo&quot;);

    Freeswitch致力于简单, 实用, 易用
</code></pre><h2 id="7-小结"><a href="#7-小结" class="headerlink" title="7.小结"></a>7.小结</h2><pre><code>常用基本技能

调试技巧

实用工具
</code></pre>
      
    </div>
    
    
    

    <div>
      
        <div>
    
        <div style="text-align:center;color: #ccc;font-size:14px;">-------------本文结束<i class="fa fa-paw"></i>感谢您的阅读-------------</div>
    
</div>

      
    </div>

    

    

    

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <!--<a href="/tags/freeswitch/" rel="tag"># freeswitch</a>-->
            <a href="/tags/freeswitch/" rel="tag"><i class="fa fa-tag"></i> freeswitch</a>
          
        </div>
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2017/12/06/2017-12-06-Git基本用法/" rel="next" title="Git基本用法">
                <i class="fa fa-chevron-left"></i> Git基本用法
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2017/12/23/2017-12-23-11.基本功能与实现/" rel="prev" title="11.基本功能与实现">
                11.基本功能与实现 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
        <!-- JiaThis Button BEGIN -->
<div class="jiathis_style">
<span class="jiathis_txt">分享到：</span>
<a class="jiathis_button_fav">收藏夹</a>
<a class="jiathis_button_copy">复制网址</a>
<a class="jiathis_button_email">邮件</a>
<a class="jiathis_button_weixin">微信</a>
<a class="jiathis_button_qzone">QQ空间</a>
<a class="jiathis_button_tqq">腾讯微博</a>
<a class="jiathis_button_douban">豆瓣</a>
<a class="jiathis_button_share">一键分享</a>

<a href="http://www.jiathis.com/share?uid=2140465" class="jiathis jiathis_txt jiathis_separator jtico jtico_jiathis" target="_blank">更多</a>
<a class="jiathis_counter_style"></a>
</div>
<script type="text/javascript" >
var jiathis_config={
  data_track_clickback:true,
  summary:"",
  shortUrl:false,
  hideMore:false
}
</script>
<script type="text/javascript" src="http://v3.jiathis.com/code/jia.js?uid=" charset="utf-8"></script>
<!-- JiaThis Button END -->
      
    </div>
  </div>


          </div>
          


          

  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <img class="site-author-image" itemprop="image"
                src="/images/ichgo.jpg"
                alt="廖壬" />
            
              <p class="site-author-name" itemprop="name">廖壬</p>
              <p class="site-description motion-element" itemprop="description">Learn to choose, to forsake, to endure loneliness, to resist temptation.</p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/archives/">
              
                  <span class="site-state-item-count">391</span>
                  <span class="site-state-item-name">日志</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                <a href="/categories/index.html">
                  <span class="site-state-item-count">11</span>
                  <span class="site-state-item-name">分类</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-tags">
                <a href="/tags/index.html">
                  <span class="site-state-item-count">56</span>
                  <span class="site-state-item-name">标签</span>
                </a>
              </div>
            

          </nav>

          
            <div class="feed-link motion-element">
              <a href="/atom.xml" rel="alternate">
                <i class="fa fa-rss"></i>
                RSS
              </a>
            </div>
          

          
            <div class="links-of-author motion-element">
                
                  <span class="links-of-author-item">
                    <a href="https://github.com/liaoren512" target="_blank" title="GitHub">
                      
                        <i class="fa fa-fw fa-github"></i>GitHub</a>
                  </span>
                
                  <span class="links-of-author-item">
                    <a href="mailto:liaoren512@gmail.com" target="_blank" title="E-Mail">
                      
                        <i class="fa fa-fw fa-envelope"></i>E-Mail</a>
                  </span>
                
                  <span class="links-of-author-item">
                    <a href="https://weibo.com/5281757990/profile?rightmod=1&wvr=6&mod=personinfo" target="_blank" title="Weibo">
                      
                        <i class="fa fa-fw fa-globe"></i>Weibo</a>
                  </span>
                
                  <span class="links-of-author-item">
                    <a href="https://www.zhihu.com" target="_blank" title="Zhihu">
                      
                        <i class="fa fa-fw fa-globe"></i>Zhihu</a>
                  </span>
                
            </div>
          

          
          

          
          

          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-调试与排错"><span class="nav-number">1.</span> <span class="nav-text">1.调试与排错</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-使用外部工具抓包"><span class="nav-number">2.</span> <span class="nav-text">2.使用外部工具抓包</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#4-originate命令示例解析"><span class="nav-number">3.</span> <span class="nav-text">4.originate命令示例解析</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-呼叫是怎么工作的"><span class="nav-number">4.</span> <span class="nav-text">5.呼叫是怎么工作的?</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#6-Freeswitch图形用户界面简介"><span class="nav-number">5.</span> <span class="nav-text">6.Freeswitch图形用户界面简介</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#7-小结"><span class="nav-number">6.</span> <span class="nav-text">7.小结</span></a></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        
<!--<script async src="https://dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"></script>-->

<div class="copyright">&copy; <span itemprop="copyrightYear">2018</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">廖壬</span>

  
</div>

<!-- 在网站底部加上访问量-->
<!--<div class="powered-by">
<i class="fa fa-user-md"></i><span id="busuanzi_container_site_uv">
  本站访客数:<span id="busuanzi_value_site_pv"></span>
</span>
</div>-->
<!--pv的方式，单个用户连续点击n篇文章，记录n次访问量-->
<!--

  <div class="powered-by">由 <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a> 强力驱动</div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">主题 &mdash; <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next">NexT.Gemini</a> v5.1.4</div>



-->
<div class="theme-info">
  <div class="powered-by"></div>
  <span class="post-count">博客全站共字</span>
</div>
        
<div class="busuanzi-count">
  <script async src="https://dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"></script>

  
    <span class="site-uv">
      <i class="fa fa-user"></i>
      <span class="busuanzi-value" id="busuanzi_value_site_uv"></span>
      
    </span>
  

  
    <span class="site-pv">
      <i class="fa fa-eye"></i>
      <span class="busuanzi-value" id="busuanzi_value_site_pv"></span>
      
    </span>
  
</div>








        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  


  



  
  









  
  
    <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  

  
  
    <script type="text/javascript" src="/lib/canvas-nest/canvas-nest.min.js"></script>
  

  
  
    <script type="text/javascript" src="/lib/three/three.min.js"></script>
  

  
  
    <script type="text/javascript" src="/lib/three/three-waves.min.js"></script>
  


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.4"></script>



  
  


  <script type="text/javascript" src="/js/src/affix.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.1.4"></script>



  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  












  

  <script type="text/javascript">
    // Popup Window;
    var isfetched = false;
    var isXml = true;
    // Search DB path;
    var search_path = "search.xml";
    if (search_path.length === 0) {
      search_path = "search.xml";
    } else if (/json$/i.test(search_path)) {
      isXml = false;
    }
    var path = "/" + search_path;
    // monitor main search box;

    var onPopupClose = function (e) {
      $('.popup').hide();
      $('#local-search-input').val('');
      $('.search-result-list').remove();
      $('#no-result').remove();
      $(".local-search-pop-overlay").remove();
      $('body').css('overflow', '');
    }

    function proceedsearch() {
      $("body")
        .append('<div class="search-popup-overlay local-search-pop-overlay"></div>')
        .css('overflow', 'hidden');
      $('.search-popup-overlay').click(onPopupClose);
      $('.popup').toggle();
      var $localSearchInput = $('#local-search-input');
      $localSearchInput.attr("autocapitalize", "none");
      $localSearchInput.attr("autocorrect", "off");
      $localSearchInput.focus();
    }

    // search function;
    var searchFunc = function(path, search_id, content_id) {
      'use strict';

      // start loading animation
      $("body")
        .append('<div class="search-popup-overlay local-search-pop-overlay">' +
          '<div id="search-loading-icon">' +
          '<i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>' +
          '</div>' +
          '</div>')
        .css('overflow', 'hidden');
      $("#search-loading-icon").css('margin', '20% auto 0 auto').css('text-align', 'center');

      $.ajax({
        url: path,
        dataType: isXml ? "xml" : "json",
        async: true,
        success: function(res) {
          // get the contents from search data
          isfetched = true;
          $('.popup').detach().appendTo('.header-inner');
          var datas = isXml ? $("entry", res).map(function() {
            return {
              title: $("title", this).text(),
              content: $("content",this).text(),
              url: $("url" , this).text()
            };
          }).get() : res;
          var input = document.getElementById(search_id);
          var resultContent = document.getElementById(content_id);
          var inputEventFunction = function() {
            var searchText = input.value.trim().toLowerCase();
            var keywords = searchText.split(/[\s\-]+/);
            if (keywords.length > 1) {
              keywords.push(searchText);
            }
            var resultItems = [];
            if (searchText.length > 0) {
              // perform local searching
              datas.forEach(function(data) {
                var isMatch = false;
                var hitCount = 0;
                var searchTextCount = 0;
                var title = data.title.trim();
                var titleInLowerCase = title.toLowerCase();
                var content = data.content.trim().replace(/<[^>]+>/g,"");
                var contentInLowerCase = content.toLowerCase();
                var articleUrl = decodeURIComponent(data.url);
                var indexOfTitle = [];
                var indexOfContent = [];
                // only match articles with not empty titles
                if(title != '') {
                  keywords.forEach(function(keyword) {
                    function getIndexByWord(word, text, caseSensitive) {
                      var wordLen = word.length;
                      if (wordLen === 0) {
                        return [];
                      }
                      var startPosition = 0, position = [], index = [];
                      if (!caseSensitive) {
                        text = text.toLowerCase();
                        word = word.toLowerCase();
                      }
                      while ((position = text.indexOf(word, startPosition)) > -1) {
                        index.push({position: position, word: word});
                        startPosition = position + wordLen;
                      }
                      return index;
                    }

                    indexOfTitle = indexOfTitle.concat(getIndexByWord(keyword, titleInLowerCase, false));
                    indexOfContent = indexOfContent.concat(getIndexByWord(keyword, contentInLowerCase, false));
                  });
                  if (indexOfTitle.length > 0 || indexOfContent.length > 0) {
                    isMatch = true;
                    hitCount = indexOfTitle.length + indexOfContent.length;
                  }
                }

                // show search results

                if (isMatch) {
                  // sort index by position of keyword

                  [indexOfTitle, indexOfContent].forEach(function (index) {
                    index.sort(function (itemLeft, itemRight) {
                      if (itemRight.position !== itemLeft.position) {
                        return itemRight.position - itemLeft.position;
                      } else {
                        return itemLeft.word.length - itemRight.word.length;
                      }
                    });
                  });

                  // merge hits into slices

                  function mergeIntoSlice(text, start, end, index) {
                    var item = index[index.length - 1];
                    var position = item.position;
                    var word = item.word;
                    var hits = [];
                    var searchTextCountInSlice = 0;
                    while (position + word.length <= end && index.length != 0) {
                      if (word === searchText) {
                        searchTextCountInSlice++;
                      }
                      hits.push({position: position, length: word.length});
                      var wordEnd = position + word.length;

                      // move to next position of hit

                      index.pop();
                      while (index.length != 0) {
                        item = index[index.length - 1];
                        position = item.position;
                        word = item.word;
                        if (wordEnd > position) {
                          index.pop();
                        } else {
                          break;
                        }
                      }
                    }
                    searchTextCount += searchTextCountInSlice;
                    return {
                      hits: hits,
                      start: start,
                      end: end,
                      searchTextCount: searchTextCountInSlice
                    };
                  }

                  var slicesOfTitle = [];
                  if (indexOfTitle.length != 0) {
                    slicesOfTitle.push(mergeIntoSlice(title, 0, title.length, indexOfTitle));
                  }

                  var slicesOfContent = [];
                  while (indexOfContent.length != 0) {
                    var item = indexOfContent[indexOfContent.length - 1];
                    var position = item.position;
                    var word = item.word;
                    // cut out 100 characters
                    var start = position - 20;
                    var end = position + 80;
                    if(start < 0){
                      start = 0;
                    }
                    if (end < position + word.length) {
                      end = position + word.length;
                    }
                    if(end > content.length){
                      end = content.length;
                    }
                    slicesOfContent.push(mergeIntoSlice(content, start, end, indexOfContent));
                  }

                  // sort slices in content by search text's count and hits' count

                  slicesOfContent.sort(function (sliceLeft, sliceRight) {
                    if (sliceLeft.searchTextCount !== sliceRight.searchTextCount) {
                      return sliceRight.searchTextCount - sliceLeft.searchTextCount;
                    } else if (sliceLeft.hits.length !== sliceRight.hits.length) {
                      return sliceRight.hits.length - sliceLeft.hits.length;
                    } else {
                      return sliceLeft.start - sliceRight.start;
                    }
                  });

                  // select top N slices in content

                  var upperBound = parseInt('1');
                  if (upperBound >= 0) {
                    slicesOfContent = slicesOfContent.slice(0, upperBound);
                  }

                  // highlight title and content

                  function highlightKeyword(text, slice) {
                    var result = '';
                    var prevEnd = slice.start;
                    slice.hits.forEach(function (hit) {
                      result += text.substring(prevEnd, hit.position);
                      var end = hit.position + hit.length;
                      result += '<b class="search-keyword">' + text.substring(hit.position, end) + '</b>';
                      prevEnd = end;
                    });
                    result += text.substring(prevEnd, slice.end);
                    return result;
                  }

                  var resultItem = '';

                  if (slicesOfTitle.length != 0) {
                    resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + highlightKeyword(title, slicesOfTitle[0]) + "</a>";
                  } else {
                    resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + title + "</a>";
                  }

                  slicesOfContent.forEach(function (slice) {
                    resultItem += "<a href='" + articleUrl + "'>" +
                      "<p class=\"search-result\">" + highlightKeyword(content, slice) +
                      "...</p>" + "</a>";
                  });

                  resultItem += "</li>";
                  resultItems.push({
                    item: resultItem,
                    searchTextCount: searchTextCount,
                    hitCount: hitCount,
                    id: resultItems.length
                  });
                }
              })
            };
            if (keywords.length === 1 && keywords[0] === "") {
              resultContent.innerHTML = '<div id="no-result"><i class="fa fa-search fa-5x" /></div>'
            } else if (resultItems.length === 0) {
              resultContent.innerHTML = '<div id="no-result"><i class="fa fa-frown-o fa-5x" /></div>'
            } else {
              resultItems.sort(function (resultLeft, resultRight) {
                if (resultLeft.searchTextCount !== resultRight.searchTextCount) {
                  return resultRight.searchTextCount - resultLeft.searchTextCount;
                } else if (resultLeft.hitCount !== resultRight.hitCount) {
                  return resultRight.hitCount - resultLeft.hitCount;
                } else {
                  return resultRight.id - resultLeft.id;
                }
              });
              var searchResultList = '<ul class=\"search-result-list\">';
              resultItems.forEach(function (result) {
                searchResultList += result.item;
              })
              searchResultList += "</ul>";
              resultContent.innerHTML = searchResultList;
            }
          }

          if ('auto' === 'auto') {
            input.addEventListener('input', inputEventFunction);
          } else {
            $('.search-icon').click(inputEventFunction);
            input.addEventListener('keypress', function (event) {
              if (event.keyCode === 13) {
                inputEventFunction();
              }
            });
          }

          // remove loading animation
          $(".local-search-pop-overlay").remove();
          $('body').css('overflow', '');

          proceedsearch();
        }
      });
    }

    // handle and trigger popup window;
    $('.popup-trigger').click(function(e) {
      e.stopPropagation();
      if (isfetched === false) {
        searchFunc(path, 'local-search-input', 'local-search-result');
      } else {
        proceedsearch();
      };
    });

    $('.popup-btn-close').click(onPopupClose);
    $('.popup').click(function(e){
      e.stopPropagation();
    });
    $(document).on('keyup', function (event) {
      var shouldDismissSearchPopup = event.which === 27 &&
        $('.search-popup').is(':visible');
      if (shouldDismissSearchPopup) {
        onPopupClose();
      }
    });
  </script>





  

  

  

  
  

  

  

  

</body>
</html>
<!-- 页面点击小红心 -->
<script type="text/javascript" src="/js/src/love.js"></script>